package com.yu.crm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.whyxzz.netreplyutil.NetReplyUtil;
import com.yu.crm.domain.pojo.CrmBuilding;
import com.yu.crm.domain.pojo.CrmDevice;
import com.yu.crm.domain.pojo.Station;
import com.yu.crm.domain.response.RegionCameraRep;
import com.yu.crm.domain.response.Camera;
import com.yu.crm.domain.response.Region;
import com.yu.crm.mapper.CrmDeviceMapper;
import com.yu.crm.utils.OnLineNotify;
import com.yu.crm.utils.QRCodeUtil;
import com.yxzz.common.config.UserCacheManager;
import com.yxzz.common.exception.GeneralException;
import com.yxzz.common.helper.DataHelpers;
import com.yxzz.common.helper.DateHelpers;
import com.yxzz.common.helper.ResourceConfigHelpers;
import com.yxzz.common.helper.valid.ValidatorHelpers;
//import com.yxzz.common.ws.WsMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.net.InetAddress;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.FutureTask;
import java.util.stream.Collectors;

/**
 * <p>
 * 后台 设备管理表 服务实现类
 * </p>
 *
 * @author ct
 * @since 2019-08-15
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class CrmDeviceService extends ServiceImpl<CrmDeviceMapper, CrmDevice> {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());


    private static DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
    private static DateFormat df2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Autowired
    UserCacheManager userCacheManager;

    @Autowired
    ObjectMapper objectMapper;

    @Autowired
    CrmBuildingService buildingService;

    @Autowired
    CrmAreaManageService areaManageService;

    /**
     * 详情
     *
     * @return
     */
    public CrmDevice detail(String deviceIndexCode) {
        QueryWrapper<CrmDevice> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("device_machine_code", deviceIndexCode);
        queryWrapper.eq("is_deleted", 0);
        return baseMapper.selectOne(queryWrapper);
    }

    /**
     * 设备状态
     *
     * @param deviceIndexCode
     */
    public void deviceStatus(String deviceIndexCode) {
        CrmDevice detail = this.detail(deviceIndexCode);
        if (DataHelpers.isEmpty(detail)) {
            return;
        }

        LocalDateTime gmtModified = detail.getGmtModified();
        Long times = 0L;
        if (DataHelpers.isNotEmpty(gmtModified)) {
            times = DateHelpers.localDateTimeToLong(gmtModified);
        }
        //获取当前时间
        long milliseconds = DateHelpers.localDateTimeToLong(DateHelpers.now());
        long intervalTime = milliseconds - times;
        //设备状态
        Integer isOnline = detail.getIsTapeOut();
        if (intervalTime <= 15) {
            //设备在线
            if (DataHelpers.isNotEmpty(isOnline) && isOnline == 0) {
                //设备从离线状态变为在线状态
                detail.setIsTapeOut(1);
                detail.setGmtModified(DateHelpers.now());
                baseMapper.updateById(detail);
            }
        } else {
            //设备离线
            if (DataHelpers.isNotEmpty(isOnline) && isOnline == 1) {
                //设备从在线状态状态变为离线
                detail.setIsTapeOut(0);
                detail.setGmtModified(DateHelpers.now());
                baseMapper.updateById(detail);
            }
        }
    }

    public Integer getStatus(String deviceIndexCode) {
        CrmDevice crmDevice = baseMapper.selectOne(new QueryWrapper<CrmDevice>().eq("device_machine_code", deviceIndexCode));
        return crmDevice.getIsTapeOut();
    }


    public void deleteByIds(String ids) {
        try {
            String substring = ids.substring(0, ids.length());
            String[] result = substring.split(",");
            List<Long> longList = new ArrayList<>();
            for (String s : result) {
                CrmDevice crmDevice = baseMapper.selectById(Long.valueOf(s));
                if (DataHelpers.isNotEmpty(crmDevice)) {
                    crmDevice.setGmtModified(LocalDateTime.now());
                    crmDevice.setIsDeleted(1);
                    ValidatorHelpers.validateDataSave(baseMapper.updateById(crmDevice));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
            throw new GeneralException("操作失败");
        }
    }

    public List<String> getDeviceCodeByType(String deviceName) {
        List<CrmDevice> crmDevices = baseMapper.selectList(new QueryWrapper<CrmDevice>().eq("is_deleted", 0)
                .eq("device_name", deviceName));
        return crmDevices.stream().map(CrmDevice::getDeviceMachineCode).collect(Collectors.toList());
    }

    public List<String> getDeviceTypeName() {
        List<CrmDevice> crmDevices = baseMapper.selectList(new QueryWrapper<CrmDevice>()
                .eq("is_deleted", 0)
                .select("DISTINCT device_name"));
        return crmDevices.stream().map(CrmDevice::getDeviceName).collect(Collectors.toList());
    }

    /**
     * 新增或修改设备信息
     *
     * @param crmDevice
     */
    public void addOrUpdate(CrmDevice crmDevice) {
        try {
//            String userId=userCacheManager.getCurrentUser().getUserId();
            if (DataHelpers.isNotEmpty(crmDevice.getId())) {
                if (!DataHelpers.isNotEmpty(crmDevice.getId())) {
                    throw new GeneralException("设备编号不能为空");
                }

                CrmDevice crmDevice1 = baseMapper.selectById(crmDevice.getId());
                if (!DataHelpers.isNotEmpty(crmDevice1)) {
                    throw new GeneralException("此设备编号有误");
                }
                //修改
                crmDevice.setGmtModified(LocalDateTime.now());
//                crmDevice.setUpdateUserId(userId);

//                if(crmDevice.getIsInlet()!=null && crmDevice1.getIsInlet()!=crmDevice.getIsInlet()){
//                    //通过判断设备出入口，生成二维码
//                    HashMap<String, String> maps = insertQrcodeByIsInlet(crmDevice.getIsInlet());
//                    if(DataHelpers.isNotEmpty(maps)){
//                        crmDevice.setDeviceSequence(maps.get("uuid"));
//                        crmDevice.setDeviceQrcode(maps.get("deviceQrcode"));
//                    }
//                }

                ValidatorHelpers.validateDataSave(baseMapper.updateById(crmDevice));
            } else {

                //通过判断设备出入口，生成二维码
//                HashMap<String, String> maps = insertQrcodeByIsInlet(crmDevice.getIsInlet());
//                if(!DataHelpers.isNotEmpty(maps)){
//                    throw new GeneralException("生成二维码失败,功能数不能为空");
//                }

                //设置排序字段
//                crmDevice.setSort(crmDevice.getSort());
//                //设置设备编号
//                crmDevice.setDeviceSequence(maps.get("uuid"));
//                crmDevice.setGmtCreate(LocalDateTime.now());
//                crmDevice.setCreateUserId(userId);
//                crmDevice.setDeviceQrcode(maps.get("deviceQrcode"));


                //新增
                ValidatorHelpers.validateDataSave(baseMapper.insert(crmDevice));
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
            throw new GeneralException("操作失败");
        }
    }


    /**
     * 通过设备编号扫码开门
     *
     * @param deviceSequence 设备编号
     * @return
     */
    public void infoByDeviceSequence(String deviceSequence) {
        try {
            //获取访客openId
            String userId = userCacheManager.getCurrentUser().getOpenId();

            QueryWrapper<CrmDevice> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("is_controlled", 0);
            queryWrapper.eq("status", 0);
            queryWrapper.eq("is_deleted", 0);
            queryWrapper.like("device_sequence", deviceSequence);
            CrmDevice crmDevice = baseMapper.selectOne(queryWrapper);

            if (DataHelpers.isNotEmpty(crmDevice)) {
                if (crmDevice.getIsTapeOut() == 2) {
                    logger.error("设备已关闭");
                    throw new GeneralException("设备已关闭");
                }

                //出入口
                Integer isInit = crmDevice.getIsInlet();
                String deviceSequence1 = crmDevice.getDeviceSequence();
                String[] split = deviceSequence1.split(",");
                if (split.length > 1) {
                    if (deviceSequence.equals(split[0])) {
                        isInit = 1;
                    } else if (deviceSequence.equals(split[1])) {
                        isInit = 2;
                    }
                }
                //改动点7
                crmDevice.setIsInlet(isInit);
//                sendWebSocket(crmDevice);
            } else {
                logger.error("此设备未开启扫码开门功能");
                throw new GeneralException("此设备未开启扫码开门功能");
            }

        } catch (GeneralException e) {
            throw new GeneralException(e.getMessage());

        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
            throw new GeneralException("操作失败");
        }
    }

    /**
     * 根据平台类型和设备类型查询设备列表
     *
     * @param platformType 平台设备或ISC设备类型  0 平台设备  1、ISC设备
     * @param deviceType   设备类型
     * @return
     */
    public RegionCameraRep listByPlatformTypeDeviceType(String platformType, String deviceType) {
//        String userId = userCacheManager.getCurrentUser().getUserId();
        QueryWrapper<CrmDevice> wrapper = new QueryWrapper<>();
        wrapper.eq("platform_type", platformType);
        wrapper.eq("device_type", deviceType);
        wrapper.eq("is_deleted", 0);
//        wrapper.eq("create_user_id",userId);
        List<CrmDevice> crmDevices = list(wrapper);
        List<Region> regions = new ArrayList<>();
        List<Camera> cameras = new ArrayList<>();
        for (CrmDevice crmDevice : crmDevices) {
            //1、获得areaBuildingType,如果为1，则根据areaBuildingId查询楼栋区域信息，若为0，则不用查询
            Region region = new Region();
            Camera camera = new Camera();
            if ("0".equals(crmDevice.getAreaBuildingType())) {
                //设置区域信息
                camera.setIndexCode("0");
                region.setIndexCode(crmDevice.getAreaBuildingId());
//                region.setParentIndexCode(crmDevice.getAreaBuildingId());
                camera.setParentIndexCode(crmDevice.getAreaBuildingId());
                camera.setName(areaManageService.getById(crmDevice.getAreaBuildingId()).getParkAreaName() + "-" + crmDevice.getDeviceName());
                region.setName(areaManageService.getById(crmDevice.getAreaBuildingId()).getParkAreaName() + "-" + crmDevice.getDeviceName());
            } else {
                //设置区域信息和楼栋信息
                CrmBuilding building = buildingService.getById(crmDevice.getAreaBuildingId());
                region.setParentIndexCode(building.getAreaManageId().toString());
                region.setIndexCode(crmDevice.getAreaBuildingId());
                region.setName(crmDevice.getDeviceName());
                camera.setParentIndexCode(building.getAreaManageId().toString());
                //摄像头如果挂载在园区上，显示indexCode为0，其他标识存在
                camera.setIndexCode(building.getId().toString());
                camera.setName(areaManageService.getById(building.getAreaManageId()).getParkAreaName() + "-" + crmDevice.getDeviceName());
            }
            //设置摄像头信息
            camera.setIp(crmDevice.getDeviceIp());
            camera.setPort(crmDevice.getDevicePort());
            camera.setUserName(crmDevice.getUserName());
            camera.setUserPasswd(crmDevice.getPassword());
            regions.add(region);
            cameras.add(camera);
        }
        if (regions.size() == 1) {
            regions.get(0).setParentIndexCode("-1");
        }
        if (cameras.size() == 1) {
            cameras.get(0).setParentIndexCode("-1");
        }
        RegionCameraRep areaRep = new RegionCameraRep();
        areaRep.setRegions(regions);
        areaRep.setCameras(cameras);
        return areaRep;
    }


    /**
     * 重新加载设备(不用改)
     */
    public void initDevice() {
        System.out.println("====重新加载!====");
        OnLineNotify onLineNotify = new OnLineNotify();
        try {
            InetAddress ia = null;
            //获取本机ip地址
            ia = ia.getLocalHost();
            //NetReplyUtil.init("192.168.10.97", 60000, onLineNotify);
            NetReplyUtil.init(ia.getHostAddress(), 60000, onLineNotify);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
            throw new GeneralException("操作失败");
        }
    }

    /**
     * 通过设备主键查询设备详情(不用改)
     *
     * @param id 设备主键
     * @return
     */
    public CrmDevice infoById(Long id) {
        try {
            return baseMapper.selectById(id);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
            throw new GeneralException("操作失败");
        }
    }

    /**
     * 通过条件查询分页设备信息
     *
     * @param page
     * @param condition 查询条件 (模糊查询  控制器名称，位置，ip地址，端口号，设备编号 )
     * @return
     */
    public IPage<CrmDevice> page(Page<CrmDevice> page, String deviceName, String condition) {
        try {
            QueryWrapper<CrmDevice> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("is_deleted", 0);
            if (DataHelpers.isNotEmptyString(deviceName)) {
                queryWrapper.eq("device_name", deviceName);
            }
            if (DataHelpers.isNotEmptyString(condition)) {
                queryWrapper.and(i -> i.like("device_name", condition)
                        .or().like("device_machine_code", condition)
                        .or().like("device_ip", condition)
                        .or().like("device_port", condition));
            }
            queryWrapper.orderByDesc("gmt_create");
            IPage<CrmDevice> crmDeviceIPage = baseMapper.selectPage(page, queryWrapper);
            List<CrmDevice> records = crmDeviceIPage.getRecords();
            if (DataHelpers.isNotEmpty(records)) {
                return crmDeviceIPage;
            } else {
//                throw new GeneralException("设备信息列表数据为空");
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
//            throw new GeneralException("操作失败");
            return null;
        }
    }

    /**
     * 批量开启/关闭设备
     *
     * @param map 批量修改  type 1 开启  2 关闭
     *            { "ids": "[1,2,3]", "type": 1 }
     */
    public void updateList(HashMap<String, Object> map) {
        try {
            Integer type = Integer.parseInt(map.get("type").toString());
            List<String> ids = objectMapper.readValue(map.get("ids").toString(), new TypeReference<List<String>>() {
            });
            if (DataHelpers.isNotEmpty(ids)) {
                baseMapper.updateList(ids, type);
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
            throw new GeneralException("转换失败");
        }
    }

    /**
     * 删除设备信息,软删除
     *
     * @param id 设备编号
     */
    public void deleteById(Long id) {
        try {
            String userId = userCacheManager.getCurrentUser().getUserId();
            CrmDevice crmDevice = baseMapper.selectById(id);
            if (DataHelpers.isNotEmpty(crmDevice)) {
                crmDevice.setGmtModified(LocalDateTime.now());
                crmDevice.setUpdateUserId(userId);
                crmDevice.setIsDeleted(1);

                ValidatorHelpers.validateDataSave(baseMapper.updateById(crmDevice));
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
            throw new GeneralException("操作失败");
        }
    }

    /**
     * 通过序列号修改在线状态
     *
     * @param crmDevice
     */
    public void updateByDeviceMachineCode(CrmDevice crmDevice) {
        try {
            baseMapper.updateByDeviceMachineCode(crmDevice);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
            throw new GeneralException("操作失败");
        }
    }

    /***********************************业务相关方法结束***********************************************/


    /***********************************调用的方法开始***********************************************/


    /**
     * 通过判断设备出入口，生成二维码
     *
     * @param isInlet 设备出入口
     * @return
     */
    private HashMap<String, String> insertQrcodeByIsInlet(Integer isInlet) {
        try {
            //生成设备编号
            String uuid = "";
            //设备对应二维码地址
            String deviceQrcode = "";
            HashMap<String, String> maps = new HashMap<>();
            if (isInlet != null && isInlet == 0) {
                //出入口
                //生成设备编号
                uuid = UUID.randomUUID().toString().replace("-", "");
                HashMap<String, String> map = encodeQrCode(ResourceConfigHelpers.getProperty("destPatjGet.url") + uuid, "qr_code/Inlet.png");
                if (!DataHelpers.isNotEmpty(map)) {
                    throw new GeneralException("生成二维码失败");
                }

                String uuid1 = UUID.randomUUID().toString().replace("-", "");
                HashMap<String, String> map1 = encodeQrCode(ResourceConfigHelpers.getProperty("destPatjGet.url") + uuid1, "qr_code/out.png");
                if (!DataHelpers.isNotEmpty(map1)) {
                    throw new GeneralException("生成二维码失败");
                }
                uuid = uuid + "," + uuid1;
                deviceQrcode = map.get("fileUrl") + "," + map1.get("fileUrl");
            } else if (isInlet != null && isInlet == 1) {
                //入口
                //生成设备编号
                uuid = UUID.randomUUID().toString().replace("-", "");
                HashMap<String, String> map = encodeQrCode(ResourceConfigHelpers.getProperty("destPatjGet.url") + uuid, "qr_code/Inlet.png");
                if (!DataHelpers.isNotEmpty(map)) {
                    throw new GeneralException("生成二维码失败");
                }
                deviceQrcode = map.get("fileUrl");
            } else if (isInlet != null && isInlet == 2) {
                //出口
                //生成设备编号
                uuid = UUID.randomUUID().toString().replace("-", "");
                HashMap<String, String> map = encodeQrCode(ResourceConfigHelpers.getProperty("destPatjGet.url") + uuid, "qr_code/out.png");
                if (!DataHelpers.isNotEmpty(map)) {
                    throw new GeneralException("生成二维码失败");
                }
                deviceQrcode = map.get("fileUrl");
            }
            maps.put("uuid", uuid);
            maps.put("deviceQrcode", deviceQrcode);
            return maps;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
            throw new GeneralException("操作失败");
        }
    }

    /**
     * 生成二维码（不显示logo二维码）
     *
     * @param content
     * @param imgPath 二维码logo地址
     * @return
     */
    public HashMap<String, String> encodeQrCode(String content, String imgPath) {
        try {
            HashMap<String, String> map = QRCodeUtil.encode(content, imgPath, ResourceConfigHelpers.getProperty(
                    "destPath.qrcode_url"), ResourceConfigHelpers.getProperty("destPathGet.qrcode_url"), true);
            return map;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
            throw new GeneralException("生成二维码失败");
        }
    }


    /**
     * 发送开门指令，并记录路线图
     *
     * @param crmDevice
     *
     */
//    private void sendWebSocket(CrmDevice crmDevice) {
//        try {
//            //长连接(发送消息)
//            WsMessage wsMessage=new WsMessage();
//            wsMessage.setContent(crmDevice);
//            wsMessage.setAction("CALL_DEVICE");
//            //实现开门操作
//            openDeviceTask(crmDevice);
//        }catch (Exception e){
//            e.printStackTrace();
//            logger.error(e.getMessage());
//            throw new GeneralException("操作失败");
//        }
//    }

    /**
     * 实现开门操作
     *
     * @param crmDevice
     */
    public void openDeviceTask(CrmDevice crmDevice) {
        try {
            System.out.println("----------------=======code====-----------------" + crmDevice.getDeviceMachineCode());
            //二维码使用(需要)
            FutureTask<Integer> task = NetReplyUtil.cloudOpen(crmDevice.getDeviceMachineCode(), 1, NetReplyUtil.NetReplyType.Wiegand_NetReply);
            System.out.println("=======第一次====");
            return;
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("=======重试========");
            try {
                Thread.sleep(500);
                FutureTask<Integer> task = NetReplyUtil.cloudOpen(crmDevice.getDeviceMachineCode(), 1, NetReplyUtil.NetReplyType.Wiegand_NetReply);
                //重新加载设备
                //initDevice();
            } catch (Exception e1) {
                if ("Net Controller invalid!".equals(e1.getMessage())) {
                    e1.printStackTrace();
                    logger.error("请稍后重试");
                    throw new GeneralException("请稍后重试");
                }
                if ("session disconnected!".equals(e1.getMessage())) {
                    logger.error("设备未开启");
                    throw new GeneralException("设备未开启");
                }
            }
        }
    }

    /**
     * 通过闸机序列号实现开门
     *
     * @param deviceId
     */
    public void openDeviceByDeviceCode(String deviceId) {
        try {
            CrmDevice crmDevice = baseMapper.selectOne(new QueryWrapper<CrmDevice>()
                    .eq("device_machine_code", deviceId)
                    .eq("is_controlled", 0)
                    .eq("status", 0)
                    .eq("is_deleted", 0)
            );
            if (DataHelpers.isNotEmpty(crmDevice)) {
                //实现开门操作
                openDeviceTask(crmDevice);
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
            throw new GeneralException("开门失败");
        }
    }

    /**
     * 通过用户id实现开门
     *
     * @param cameraNumber
     */
    public void openDevice(String cameraNumber) {
        try {
            QueryWrapper<CrmDevice> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.eq("is_controlled", 0);
            queryWrapper1.eq("status", 0);
            queryWrapper1.eq("is_deleted", 0);
            queryWrapper1.like("camera_number", cameraNumber);
            CrmDevice crmDevice = baseMapper.selectOne(queryWrapper1);
            if (DataHelpers.isNotEmpty(crmDevice)) {
                //实现开门操作
                openDeviceTask(crmDevice);
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
            throw new GeneralException("开门失败");
        }
    }

    public CrmDevice infoByCameraNumber(String cameraNumber) {
        QueryWrapper<CrmDevice> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("camera_number", cameraNumber);
        queryWrapper.eq("is_deleted", 0);
        return baseMapper.selectOne(queryWrapper);
    }
}
